home *** CD-ROM | disk | FTP | other *** search
/ Chip 1997 December / CHIPNET Aralık 1997.iso / linux / redhat / misc / src / install / net.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-11  |  28.7 KB  |  1,144 lines

  1. #include <linux/if.h>
  2. #include <linux/route.h>
  3. #include <sys/ioctl.h>
  4. #include <sys/time.h>
  5. #include <sys/types.h>
  6.  
  7. #include <ctype.h>
  8. #include <errno.h>
  9. #include <netinet/in.h>
  10. #include <netinet/ip.h>
  11. #include <arpa/inet.h>
  12. #include <resolv.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <unistd.h>
  17.  
  18. #include "bootpc.h"
  19. #include "devices.h"
  20. #include "install.h"
  21. #include "log.h"
  22. #include "newt.h"
  23. #include "net.h"
  24. #include "perror.h"
  25. #include "windows.h"
  26.  
  27. struct intfconfig_s {
  28.     newtComponent ipLabel, nmLabel, gwLabel, nsLabel;
  29.     newtComponent ipEntry, nmEntry, gwEntry, nsEntry;
  30.     char * ip, * nm, * gw, * ns;
  31.     char * bootpState;
  32. };
  33.  
  34. struct netconfig_s {
  35.     newtComponent nsLabels[3], hnLabel, dnLabel;
  36.     newtComponent nsEntrys[3], hnEntry, dnEntry;
  37.     char * ns[3], * gw, * hn, * dn;
  38. };
  39.  
  40. static void ipCallback(newtComponent co, void * data);
  41. static void hnCallback(newtComponent co, void * data);
  42.  
  43. /* It's a bit gross, but setupNetworkInterface() will setup your general
  44.    networking information if bootp is used */
  45. static int setupNetworkInterface(struct netInterface * intf,
  46.                  struct netConfig * netc,
  47.                      struct driversLoaded ** dl, int justConfig);
  48. static int doBringUpNetworking(struct netInterface * intf, 
  49.                    struct netConfig * netc,
  50.                    struct driversLoaded ** dl, int justConfig);
  51. static int configureNetDevice(struct netInterface * intf);
  52. /* intf in configureNetwork is optional */
  53. static int configureNetwork(struct netConfig * netc, 
  54.                 struct netInterface * intf);
  55.  
  56. static int doBootp(char * device, struct netInterface * intf,
  57.            struct netConfig * netc) {
  58.     struct netInterface minInterface;
  59.     int rc;
  60.  
  61.     if (testing) return 1;
  62.  
  63.     /* This is a bit of a hack, but it lets us use Jon Peatfield's bootp
  64.         code w/o hacking at it */
  65.  
  66.     logMessage("using bootp for device %s", device);
  67.  
  68.     minInterface.ip = minInterface.netmask = minInterface.network = 0;
  69.     minInterface.broadcast = 0xffffffff; 
  70.     strcpy(minInterface.dev, device);
  71.  
  72.     if (configureNetDevice(&minInterface)) {
  73.     logMessage("failed to setup minimal bootp interface %s", device);
  74.     return 1;
  75.     }
  76.  
  77.     winStatus(40, 3, "BOOTP", "Sending BOOTP request...");
  78.     rc = performBootp(device, "255.255.255.255", "", 10, 0, NULL, 0, 1,
  79.             BP_PUT_ENV);
  80.     newtPopWindow();
  81.  
  82.     if (rc) {
  83.     logMessage("performBootp() failed w/ return %d", rc);
  84.     return 1;
  85.     }
  86.  
  87.     if (!getenv("BOOTP_IPADDR")) {
  88.     errorWindow("bootp query did not return an IP address");
  89.     return 1;
  90.     }
  91.     
  92.     /* These will be generated by bootpc.c even if they're not in the
  93.        bootp reply */
  94.  
  95.     inet_aton(getenv("BOOTP_IPADDR"), (struct in_addr *) &intf->ip);
  96.     inet_aton(getenv("BOOTP_NETMASK"), (struct in_addr *) &intf->netmask);
  97.     inet_aton(getenv("BOOTP_BROADCAST"), (struct in_addr *) 
  98.             &intf->broadcast);
  99.     inet_aton(getenv("BOOTP_NETWORK"), (struct in_addr *) 
  100.             &intf->network);
  101.  
  102.     intf->useBootp = 1;
  103.     intf->isConfigured = 1;
  104.     strcpy(intf->dev, device);
  105.  
  106.     if (getenv("BOOTP_GATEWAYS_1")) {
  107.     strcpy(netc->defaultGateway, getenv("BOOTP_GATEWAYS_1"));
  108.     netc->isConfigured = 1;
  109.     }
  110.  
  111.     if (getenv("BOOTP_DNSSRVS_1")) {
  112.     netc->nameserver[0] = strdup(getenv("BOOTP_DNSSRVS_1"));
  113.     netc->isConfigured = 1;
  114.     if (getenv("BOOTP_DNSSRVS_2"))  {
  115.         netc->nameserver[1] = strdup(getenv("BOOTP_DNSSRVS_2"));
  116.         if (getenv("BOOTP_DNSSRVS_3")) 
  117.         netc->nameserver[2] = strdup(getenv("BOOTP_DNSSRVS_3"));
  118.     }
  119.     }
  120.  
  121.     /* 
  122.     If bootp gave us a hostname and domain, use those. Otherwise,
  123.     we'll try and query the nameserver a bit later on. If that fails
  124.     as well, we'll try and use just the hostname BOOTP gave us.
  125.     */
  126.  
  127.     if (getenv("BOOTP_HOSTNAME") && getenv("BOOTP_DOMAIN")) {
  128.     logMessage("bootp returned hostname and domain name");
  129.     strcpy(netc->hostname, getenv("BOOTP_HOSTNAME"));
  130.     netc->isConfigured = 1;
  131.  
  132.     strcpy(netc->domainname, getenv("BOOTP_DOMAIN"));
  133.  
  134.     if (strcmp(netc->hostname, netc->domainname) &&
  135.         !strstr(netc->hostname, netc->domainname)) {
  136.         strcat(netc->hostname, ".");
  137.         strcat(netc->hostname, netc->domainname);
  138.     }
  139.     } 
  140.  
  141.     return 0;
  142. }
  143.  
  144. /* The interface/gateway needs to be configured before this will work! */
  145. static int guessHostname(struct netInterface * intf, struct netConfig * netc) {
  146.     struct in_addr addr;
  147.     char ips[50];
  148.  
  149.     if (intf->isUp && netc->nameserver[0]) {
  150.     logMessage("using nameserver to find host and domain name");
  151.     writeResolvConf("/etc", netc);
  152.     memcpy(&addr, &intf->ip, sizeof(addr));
  153.     strcpy(ips, inet_ntoa(addr));
  154.     winStatus(40, 3, "Hostname", "Determing host name and domain...");
  155.         if (in2host(ips, BP_PUT_ENV)) {
  156.         newtPopWindow();
  157.         logMessage("reverse name lookup failed");
  158.  
  159.         if (getenv("BOOTP_HOSTNAME")) {
  160.         strcpy(netc->hostname, getenv("BOOTP_HOSTNAME"));
  161.         } 
  162.     } else {
  163.         newtPopWindow();
  164.         logMessage("reverse name lookup worked");
  165.         strcpy(netc->hostname, getenv("BOOTP_HOSTFULL"));
  166.         strcpy(netc->domainname, getenv("BOOTP_HOSTDOMAIN"));
  167.     }
  168.     }
  169.  
  170.     return 0;
  171. }
  172.  
  173. int addDefaultRoute(struct netConfig netc) {
  174.     int s;
  175.     struct rtentry route;
  176.     struct sockaddr_in addr;
  177.  
  178.     if (testing) return 0;
  179.  
  180.     if (!strlen(netc.defaultGateway)) return 0;
  181.  
  182.     s = socket(AF_INET, SOCK_DGRAM, 0);
  183.     if (s < 0) {
  184.     close(s);
  185.     errorWindow("socket: %s");
  186.     return 1;
  187.     }
  188.  
  189.     memset(&route, 0, sizeof(route));
  190.  
  191.     addr.sin_family = AF_INET;
  192.     addr.sin_port = 0;
  193.     inet_aton(netc.defaultGateway, &addr.sin_addr);
  194.     memcpy(&route.rt_gateway, &addr, sizeof(addr));
  195.  
  196.     addr.sin_addr.s_addr = INADDR_ANY;
  197.     memcpy(&route.rt_dst, &addr, sizeof(addr));
  198.     memcpy(&route.rt_genmask, &addr, sizeof(addr));
  199.  
  200.     route.rt_flags = RTF_UP | RTF_GATEWAY;
  201.     route.rt_metric = 0;
  202.  
  203.     if (ioctl(s, SIOCADDRT, &route)) {
  204.     close(s);
  205.     errorWindow("SIOCADDRT: %s");
  206.     return 1;
  207.     }
  208.  
  209.     return 0;
  210. }
  211.  
  212. static int configureNetDevice(struct netInterface * intf) {
  213.     struct ifreq req;
  214.     struct rtentry route;
  215.     int s;
  216.     struct sockaddr_in addr;
  217.     struct in_addr ia;
  218.     char ip[20], nm[20], nw[20], bc[20];
  219.  
  220.     addr.sin_family = AF_INET;
  221.     addr.sin_port = 0;
  222.  
  223.     memcpy(&ia, &intf->ip, sizeof(intf->ip));
  224.     strcpy(ip, inet_ntoa(ia));
  225.  
  226.     memcpy(&ia, &intf->netmask, sizeof(intf->netmask));
  227.     strcpy(nm, inet_ntoa(ia));
  228.  
  229.     memcpy(&ia, &intf->broadcast, sizeof(intf->broadcast));
  230.     strcpy(bc, inet_ntoa(ia));
  231.  
  232.     memcpy(&ia, &intf->network, sizeof(intf->network));
  233.     strcpy(nw, inet_ntoa(ia));
  234.  
  235.     logMessage("configuring %s ip: %s nm: %s nw: %s bc: %s", intf->dev,
  236.         ip, nm, nw, bc);
  237.  
  238.     if (testing) return 0;
  239.     
  240.     strcpy(req.ifr_name, intf->dev);
  241.     addr.sin_family = AF_INET;
  242.     addr.sin_port = 0;
  243.     memcpy(&addr.sin_addr, &intf->ip, sizeof(intf->ip));
  244.  
  245.     s = socket(AF_INET, SOCK_DGRAM, 0);
  246.     if (s < 0) {
  247.     errorWindow("socket: %s");
  248.     return 1;
  249.     }
  250.  
  251.     memcpy(&req.ifr_addr, &addr, sizeof(addr));
  252.     if (ioctl(s, SIOCSIFADDR, &req)) {
  253.     close(s);
  254.     errorWindow("SIOCSIFADDR: %s");
  255.     return 1;
  256.     }
  257.  
  258.     memcpy(&addr.sin_addr, &intf->broadcast, sizeof(intf->broadcast));
  259.     memcpy(&req.ifr_broadaddr, &addr, sizeof(addr));
  260.     if (ioctl(s, SIOCSIFBRDADDR, &req)) {
  261.     close(s);
  262.     errorWindow("SIOCSIFNETMASK: %s");
  263.     return 1;
  264.     }
  265.  
  266.     memcpy(&addr.sin_addr, &intf->netmask, sizeof(intf->netmask));
  267.     memcpy(&req.ifr_netmask, &addr, sizeof(addr));
  268.     if (ioctl(s, SIOCSIFNETMASK, &req)) {
  269.     close(s);
  270.     errorWindow("SIOCSIFNETMASK: %s");
  271.     return 1;
  272.     }
  273.  
  274.     if (intf->isPtp)
  275.     req.ifr_flags = IFF_UP | IFF_RUNNING | IFF_POINTOPOINT | IFF_NOARP;
  276.     else
  277.     req.ifr_flags = IFF_UP | IFF_RUNNING | IFF_BROADCAST;
  278.  
  279.     if (ioctl(s, SIOCSIFFLAGS, &req)) {
  280.     close(s);
  281.     errorWindow("SIOCSIFFLAGS: %s");
  282.     return 1;
  283.     }
  284.  
  285.     memset(&route, 0, sizeof(route));
  286.     route.rt_dev = intf->dev;
  287.     route.rt_flags = RTF_UP;
  288.  
  289.     memcpy(&addr.sin_addr, &intf->network, sizeof(intf->netmask));
  290.     memcpy(&route.rt_dst, &addr, sizeof(addr));
  291.  
  292.     memcpy(&addr.sin_addr, &intf->netmask, sizeof(intf->netmask));
  293.     memcpy(&route.rt_genmask, &addr, sizeof(addr));
  294.  
  295.     if (ioctl(s, SIOCADDRT, &route)) {
  296.     close(s);
  297.     errorWindow("SIOCADDRT: %s");
  298.     return 1;
  299.     }
  300.  
  301.     intf->isUp = 1;
  302.  
  303.     return 0;
  304. }
  305.  
  306. int netDeviceAvailable(char * device) {
  307.     struct ifreq req;
  308.     int s;
  309.     
  310.     s = socket(AF_INET, SOCK_DGRAM, 0);
  311.     if (s < 0) {
  312.     close(s);
  313.     errorWindow("socket: %s");
  314.     return 1;
  315.     }
  316.  
  317.     strcpy(req.ifr_name, device);
  318.  
  319.     if (ioctl(s, SIOCGIFFLAGS, &req)) {
  320.     /* if we can't get the flags, the networking device isn't available */
  321.     close(s);
  322.     return 0;
  323.     }
  324.   
  325.     return 1;
  326. }
  327.  
  328. static void interfaceConfigToggle(newtComponent co, void * arg) {
  329.     struct intfconfig_s * info = arg;
  330.     int sense = NEWT_FLAGS_SET;
  331.  
  332.     if (*info->bootpState == ' ') 
  333.     sense = NEWT_FLAGS_RESET;
  334.  
  335.     newtEntrySetFlags(info->ipEntry, NEWT_ENTRY_DISABLED, sense);
  336.     newtEntrySetFlags(info->nmEntry, NEWT_ENTRY_DISABLED, sense);
  337.     newtEntrySetFlags(info->gwEntry, NEWT_ENTRY_DISABLED, sense);
  338.     newtEntrySetFlags(info->nsEntry, NEWT_ENTRY_DISABLED, sense);
  339.  
  340.     newtRefresh();
  341. }
  342.  
  343. static int setupNetworkInterface(struct netInterface * intf,
  344.                  struct netConfig * netc,
  345.                      struct driversLoaded ** dl, int justConfig) {
  346.     newtComponent okay, cancel, bootp, f, answer;
  347.     int top = 4;
  348.     struct intfconfig_s c;
  349.     struct in_addr addr;
  350.     int32 ptpNetmask;
  351.     int rc;
  352.     int done = 0;
  353.     char useBootp;
  354.     char * device = NULL;
  355.     char * devices[] = { "eth0", "tr0", "plip0", "plip1", "plip2", NULL };
  356.     char ** deviceptr;
  357.     struct driversLoaded * adriver;
  358.  
  359.     /* I should probably ask which device to use if multiple ones are
  360.        available -- oh well :-( */
  361.     for (deviceptr = devices; *deviceptr; deviceptr++) {
  362.     if (netDeviceAvailable(*deviceptr)) {
  363.         device = *deviceptr;
  364.         logMessage("%s is available -- using it for networking", device);
  365.         break;
  366.     }
  367.     }
  368.  
  369.     if (!device) {
  370.     if ((rc = loadDeviceDriver(DRIVER_NET, dl)))
  371.         return rc;
  372.  
  373.     for (adriver = *dl; adriver && adriver->type != DRIVER_NET; 
  374.         adriver = adriver->next);
  375.     if (!adriver) {
  376.         logMessage("ack! loadDriveDriver() worked but didn't load a "
  377.             "DRIVE_NET!!");
  378.         return INST_ERROR;
  379.     }
  380.  
  381.     switch (adriver->minor) {
  382.       case DRIVER_MINOR_ETHERNET:    device = "eth0"; break;
  383.       case DRIVER_MINOR_TR:        device = "tr0"; break;
  384.       case DRIVER_MINOR_PLIP:    device = getPlipDeviceName(); break;
  385.       default:            exit(1); /* ack! */
  386.     }
  387.     }
  388.  
  389.     newtOpenWindow(15, 4, 50, 15, "Configure TCP/IP");
  390.  
  391.     c.ipLabel = newtLabel(1, top + 2, "IP address:");
  392.     c.nmLabel = newtLabel(1, top + 3, "Netmask:");
  393.     c.gwLabel = newtLabel(1, top + 4, "Default gateway (IP):");
  394.     c.nsLabel = newtLabel(1, top + 5, "Primary nameserver:");
  395.    
  396.     if (!intf->ip){
  397.     c.ipEntry = newtEntry(25, top + 2, "", 16, &c.ip, 0);
  398.     } else {
  399.     memcpy(&addr, &intf->ip, sizeof(intf->ip));
  400.     c.ipEntry = newtEntry(25, top + 2, inet_ntoa(addr), 16, &c.ip, 0);
  401.     }
  402.  
  403.     if (!intf->netmask){
  404.     c.nmEntry = newtEntry(25, top + 3, "", 16, &c.nm, 0);
  405.     } else {
  406.     memcpy(&addr, &intf->netmask, sizeof(intf->netmask));
  407.     c.nmEntry = newtEntry(25, top + 3, inet_ntoa(addr), 16, &c.nm, 0);
  408.     }
  409.  
  410.     if (!netc->defaultGateway) 
  411.     c.gwEntry = newtEntry(25, top + 4, "", 16, &c.gw, 0);
  412.     else
  413.     c.gwEntry = newtEntry(25, top + 4, netc->defaultGateway, 16, &c.gw, 0);
  414.  
  415.  
  416.     if (!netc->nameserver[0]) 
  417.     c.nsEntry = newtEntry(25, top + 5, "", 16, &c.ns, 0);
  418.     else
  419.     c.nsEntry = newtEntry(25, top + 5, netc->nameserver[0], 16, &c.gw, 0);
  420.     
  421.     c.bootpState = &useBootp;
  422.    
  423.     f = newtForm(NULL, NULL, 0);
  424.  
  425.     bootp = newtCheckbox(1, top, "Configure device with bootp", 
  426.              (intf->isConfigured && intf->useBootp) ? '*' : ' ', 
  427.              NULL, &useBootp);
  428.  
  429.     newtComponentAddCallback(bootp, interfaceConfigToggle, &c);
  430.  
  431.     newtFormAddComponents(f, bootp, c.ipLabel, c.nmLabel, c.gwLabel, c.nsLabel, 
  432.                  c.ipEntry, c.nmEntry, c.gwEntry, c.nsEntry, NULL);
  433.  
  434.     if (c.bootpState)
  435.     newtFormSetCurrent(f, c.ipEntry);
  436.  
  437.     newtComponentAddCallback(c.ipEntry, ipCallback, &c);
  438.     newtComponentAddCallback(c.nmEntry, ipCallback, &c);
  439.  
  440.     okay = newtButton(8, top + 7, "Ok");
  441.     cancel = newtButton(28, top + 7, "Cancel");
  442.  
  443.     newtFormAddComponents(f, okay, cancel, NULL);
  444.  
  445.     do {
  446.     answer = newtRunForm(f);
  447.  
  448.     if (answer == cancel) {
  449.         newtFormDestroy(f);
  450.         newtPopWindow();
  451.  
  452.         return INST_CANCEL;
  453.     }
  454.  
  455.     if (useBootp != ' ') {
  456.         logMessage("Configuring device %s via bootp", device);
  457.         if (justConfig) {
  458.         done = 1;
  459.         } else if (!doBootp(device, intf, netc)) {
  460.         done = 1;
  461.         }
  462.     } else {
  463.         strcpy(intf->dev, device);
  464.         inet_aton(c.ip, (struct in_addr *) &intf->ip);
  465.         inet_aton(c.nm, (struct in_addr *) &intf->netmask);
  466.         intf->broadcast = (intf->ip & intf->netmask) | (~intf->netmask);
  467.  
  468.         inet_aton("255.255.255.255", (struct in_addr *) &ptpNetmask);
  469.  
  470.         if (ptpNetmask == intf->netmask) {
  471.         logMessage("configuring point to point device");
  472.         inet_aton(c.gw, (struct in_addr *) &intf->network);
  473.         intf->isPtp = 1;
  474.         } else {
  475.         intf->network = intf->ip & intf->netmask;
  476.         intf->isPtp = 0;
  477.         }
  478.  
  479.         intf->isConfigured = 1;
  480.  
  481.         strcpy(netc->defaultGateway, c.gw);
  482.  
  483.         if (netc->nameserver[0]) free(netc->nameserver[0]);
  484.  
  485.         if (strlen(c.ns))
  486.         netc->nameserver[0] = strdup(c.ns);
  487.         else
  488.         netc->nameserver[0] = NULL;
  489.         
  490.         netc->isConfigured = 1;
  491.  
  492.         done = 1;
  493.     }
  494.     } while (!done);
  495.  
  496.     newtFormDestroy(f);
  497.     newtPopWindow();
  498.  
  499.     if (!justConfig) {
  500.     if (configureNetDevice(intf)) return INST_ERROR;
  501.     if (addDefaultRoute(*netc)) return INST_ERROR;
  502.     }
  503.  
  504.     return 0;
  505.  
  506. static void hnCallback(newtComponent co, void * dptr) {
  507.     char * buf;
  508.     struct netconfig_s * data = dptr;
  509.  
  510.     if (strlen(data->hn)) return;
  511.     if (!strlen(data->dn)) return;
  512.  
  513.     buf = alloca(strlen(data->dn) + 5);
  514.     strcpy(buf, ".");
  515.     strcat(buf, data->dn);
  516.     
  517.     newtEntrySet(data->hnEntry, buf, 0);
  518. }
  519.  
  520. static void ipCallback(newtComponent co, void * dptr) {
  521.     struct intfconfig_s * data = dptr;
  522.     struct in_addr ipaddr, nmaddr, addr;
  523.     char * ascii;
  524.     int32 broadcast, network;
  525.  
  526.     if (co == data->ipEntry) {
  527.     if (strlen(data->ip) && !strlen(data->nm)) {
  528.         if (inet_aton(data->ip, &ipaddr)) {
  529.         ipaddr.s_addr = ntohl(ipaddr.s_addr);
  530.         if (((ipaddr.s_addr & 0xFF000000) >> 24) <= 127)
  531.             ascii = "255.0.0.0";
  532.         else if (((ipaddr.s_addr & 0xFF000000) >> 24) <= 191)
  533.             ascii = "255.255.0.0";
  534.         else 
  535.             ascii = "255.255.255.0";
  536.         newtEntrySet(data->nmEntry, ascii, 1);
  537.         }
  538.     }
  539.     } else if (co == data->nmEntry) {
  540.     if (!strlen(data->ip) || !strlen(data->nm)) return;
  541.     if (!inet_aton(data->ip, &ipaddr)) return;
  542.     if (!inet_aton(data->nm, &nmaddr)) return;
  543.  
  544.         network = ipaddr.s_addr & nmaddr.s_addr;
  545.     broadcast = (ipaddr.s_addr & nmaddr.s_addr) | (~nmaddr.s_addr);
  546.  
  547.     addr.s_addr = htonl(ntohl(broadcast) - 1);
  548.     newtEntrySet(data->gwEntry, inet_ntoa(addr), 1);
  549.  
  550.     /* I'm such a lazy bastard */
  551.     if ((ntohl(network) & 0xFFFFFF00) == 0xc7b71800) {
  552.         newtEntrySet(data->nsEntry, "199.183.24.1", 1);
  553.     } else {
  554.         addr.s_addr = htonl(ntohl(network) + 1);
  555.         newtEntrySet(data->nsEntry, inet_ntoa(addr), 1);
  556.     }
  557.     }
  558. }
  559.  
  560. int writeNetConfig(char * prefix, struct netConfig * netc, 
  561.            struct netInterface * gwdev, int verbose) {
  562.     char filename[100];
  563.     FILE * f;
  564.  
  565.     if (testing) return 0;
  566.  
  567.     sprintf(filename, "%s/network", prefix);
  568.  
  569.     f = fopen(filename, "w");
  570.     if (!f) {
  571.     errorWindow("cannot create network config file: %s");
  572.     return INST_ERROR;
  573.     }
  574.  
  575.     fprintf(f, "NETWORKING=yes\n");
  576.  
  577.     logMessage("writing network information to %s", filename);
  578.  
  579.     if (netc->hostname && strlen(netc->hostname)) {
  580.     logMessage("\tnetwork is configured, writing complete information");
  581.     fprintf(f, "HOSTNAME=%s\n", netc->hostname);
  582.     fprintf(f, "DOMAINNAME=%s\n", netc->domainname);
  583.  
  584.     if (gwdev && strlen(netc->defaultGateway)) {
  585.         fprintf(f, "GATEWAY=%s\n", netc->defaultGateway);
  586.         fprintf(f, "GATEWAYDEV=%s\n", gwdev->dev);
  587.     }
  588.  
  589.     if (verbose) {
  590.         if (netc->nameserver[0])
  591.         fprintf(f, "NS1=%s\n", netc->nameserver[0]);
  592.         
  593.         if (netc->nameserver[1])
  594.         fprintf(f, "NS2=%s\n", netc->nameserver[1]);
  595.         
  596.         if (netc->nameserver[2])
  597.         fprintf(f, "NS3=%s\n", netc->nameserver[2]);
  598.     }
  599.     } else {
  600.     logMessage("\tnetwork is not configured");
  601.     fprintf(f, "HOSTNAME=localhost.localdomain\n");
  602.     }
  603.  
  604.     fclose(f);
  605.  
  606.     return 0;
  607. }
  608.  
  609. int writeHosts(char * prefix, struct netConfig * netc, 
  610.            struct netInterface * intf) {
  611.     char filename[100];
  612.     FILE * f;
  613.     struct in_addr * addrptr;
  614.     char * nickname;
  615.     int i;
  616.  
  617.     if (testing) return 1;
  618.  
  619.     sprintf(filename, "%s/hosts", prefix);
  620.  
  621.     /* if /etc/hosts already exists, don't bother creating one */
  622.     if (!access(filename, R_OK)) {
  623.     logMessage("%s already exists -- won't crunch it", filename);
  624.     return 0;
  625.     }
  626.     logMessage("%s doesn not exist -- creating", filename);
  627.  
  628.     f = fopen(filename, "w");
  629.     if (!f) {
  630.     errorWindow("cannot create /etc/hosts: %s");
  631.     return INST_ERROR;
  632.     }
  633.  
  634.     logMessage("writing host information to %s", filename);
  635.  
  636.     fprintf(f, "127.0.0.1\t\tlocalhost localhost.localdomain\n");
  637.     if (netc->hostname && strlen(netc->hostname)) {
  638.     addrptr = (struct in_addr *) &intf->ip;
  639.     i = strlen(netc->hostname) - strlen(netc->domainname);
  640.     if (i > 1 && !strcmp(netc->hostname + i, netc->domainname)
  641.         && netc->hostname[i - 1] == '.') {
  642.         nickname = strdup(netc->hostname);
  643.         nickname[i - 1] = '\0';
  644.         fprintf(f, "%s\t\t%s %s\n", inet_ntoa(*addrptr),
  645.             netc->hostname, nickname);
  646.         free(nickname);
  647.     } else {
  648.         fprintf(f, "%s\t\t%s\n", inet_ntoa(*addrptr),
  649.             netc->hostname);
  650.     }
  651.  
  652.     sethostname(netc->hostname, strlen(netc->hostname));
  653.     }
  654.  
  655.     fclose(f);
  656.  
  657.     res_init();        /* reinit the resolver so DNS changes take affect */
  658.  
  659.     return 0;
  660. }
  661.  
  662. int writeResolvConf(char * prefix, struct netConfig * netc) {
  663.     char filename[100];
  664.     FILE * f;
  665.  
  666.     if (testing) return 1;
  667.  
  668.     if (!netc->domainname && !netc->nameserver[0]) {
  669.     logMessage("networking is not configured - not writing resolv.conf");
  670.     return 0;
  671.     }
  672.  
  673.     sprintf(filename, "%s/resolv.conf", prefix);
  674.  
  675.     f = fopen(filename, "w");
  676.     if (!f) {
  677.     errorWindow("cannot create resolv.conf: %s");
  678.     return INST_ERROR;
  679.     }
  680.  
  681.     logMessage("writing nameservices information to %s", filename);
  682.  
  683.     if (netc->domainname)
  684.     fprintf(f, "search %s\n", netc->domainname);
  685.  
  686.     if (netc->nameserver[0])
  687.     fprintf(f, "nameserver %s\n", netc->nameserver[0]);
  688.     
  689.     if (netc->nameserver[1])
  690.     fprintf(f, "nameserver %s\n", netc->nameserver[1]);
  691.     
  692.     if (netc->nameserver[2])
  693.     fprintf(f, "nameserver %s\n", netc->nameserver[2]);
  694.  
  695.     fclose(f);
  696.  
  697.     res_init();        /* reinit the resolver so DNS changes take affect */
  698.  
  699.     return 0;
  700. }
  701.  
  702. int writeNetInterfaceConfig(char * prefix, struct netInterface * intf) {
  703.     char filename[100];
  704.     FILE * f;
  705.     struct in_addr * addrptr;
  706.  
  707.     if (testing) return 0;
  708.  
  709.     if (!intf->isConfigured) {
  710.     logMessage("network interface is not configured - not creating "
  711.            "ifcfg-*");
  712.     return(0);
  713.     }
  714.  
  715.     sprintf(filename, "%s/ifcfg-%s", prefix, intf->dev);
  716.  
  717.     f = fopen(filename, "w");
  718.     if (!f) {
  719.     errorWindow("cannot create network device config file: %s");
  720.     return INST_ERROR;
  721.     }
  722.  
  723.     logMessage("writing network information to %s", filename);
  724.     
  725.     fprintf(f, "DEVICE=%s\n", intf->dev);
  726.  
  727.     if (intf->useBootp) fprintf(f, "BOOTP=yes\n");
  728.  
  729.     addrptr = (struct in_addr *) &intf->ip;
  730.     fprintf(f, "IPADDR=%s\n", inet_ntoa(*addrptr));
  731.  
  732.     addrptr = (struct in_addr *) &intf->netmask;
  733.     fprintf(f, "NETMASK=%s\n", inet_ntoa(*addrptr));
  734.  
  735.     addrptr = (struct in_addr *) &intf->network;
  736.     fprintf(f, "NETWORK=%s\n", inet_ntoa(*addrptr));
  737.  
  738.     addrptr = (struct in_addr *) &intf->broadcast;
  739.     fprintf(f, "BROADCAST=%s\n", inet_ntoa(*addrptr));
  740.  
  741.     fprintf(f, "ONBOOT=yes\n");
  742.  
  743.     fclose(f);
  744.  
  745.     return 0;
  746. }
  747.  
  748. int readNetInterfaceConfig(char * prefix, char * device, 
  749.                 struct netInterface * intf) {
  750.     FILE * f;
  751.     char * start, * end;
  752.     char buf[250];
  753.     int line = 0;
  754.  
  755.     intf->isConfigured = 0;
  756.  
  757.     if (testing) {
  758.     return 0;
  759.     }
  760.  
  761.     sprintf(buf, "%s/ifcfg-%s", prefix, device);
  762.  
  763.     f = fopen(buf, "r");
  764.     if (!f) {
  765.     if (errno != ENOENT) {
  766.         errorWindow("cannot open file: %s");
  767.         return INST_ERROR;
  768.     } else {
  769.         intf->ip = 0;
  770.         return 0;
  771.     }
  772.     }
  773.  
  774.     while (fgets(buf, sizeof(buf) - 1, f)) {
  775.     line++;
  776.  
  777.     start = buf;
  778.  
  779.     /* skipping leading spaces */
  780.     while (*start && isspace(*start)) start++;
  781.     if (!*start) continue;
  782.  
  783.     /* skip comments */
  784.     if (*start == '#') continue;
  785.  
  786.     /* cut off trailing spaces and \n */
  787.     end = start + strlen(start) - 2;
  788.     while (isspace(*end)) end--;
  789.     end++;
  790.     *end = '\0';    
  791.     end--;
  792.     
  793.     if (!strncmp("IPADDR=", start, 7)) {
  794.         start += 7;
  795.         inet_aton(start, (struct in_addr *) &intf->ip);
  796.     } else if (!strncmp("DEVICE=", start, 7)) {
  797.         start += 7;
  798.         strcpy(intf->dev, start);
  799.     } else if (!strncmp("BOOTP=", start, 6)) {
  800.         intf->useBootp = 1;
  801.     } else if (!strncmp("NETMASK=", start, 8)) {
  802.         start += 8;
  803.         inet_aton(start, (struct in_addr *) &intf->netmask);
  804.     } else if (!strncmp("NETWORK=", start, 8)) {
  805.         start += 8;
  806.         inet_aton(start, (struct in_addr *) &intf->network);
  807.         if (!strcmp(start, "255.255.255.255"))
  808.         intf->isPtp = 1;
  809.     } else if (!strncmp("BROADCAST=", start, 10)) {
  810.         start += 10;
  811.         inet_aton(start, (struct in_addr *) &intf->broadcast);
  812.     }
  813.     }
  814.  
  815.     fclose(f);
  816.  
  817.     intf->isConfigured = 1;
  818.  
  819.     return 0;
  820. }
  821.  
  822. int configureNetwork(struct netConfig * netc, 
  823.              struct netInterface * intf) {
  824.     struct netconfig_s n;
  825.     int top = 3;
  826.     newtComponent f, okay, cancel, answer;
  827.     int i;
  828.  
  829.     newtOpenWindow(15, 4, 50, 15, "Configure Network");
  830.  
  831.     n.dnLabel = newtLabel(1, top    , "Domain name:");
  832.     n.hnLabel = newtLabel(1, top + 1, "Host name:");
  833.     n.nsLabels[1] = newtLabel(1, top + 2, "Secondary nameserver (IP):");
  834.     n.nsLabels[2] = newtLabel(1, top + 3, "Tertiary nameserver (IP):");
  835.  
  836.     n.dnEntry = newtEntry(28, top    , "", 20, &n.dn, NEWT_ENTRY_SCROLL);
  837.     n.hnEntry = newtEntry(28, top + 1, "", 20, &n.hn, NEWT_ENTRY_SCROLL);
  838.     n.nsEntrys[1] = newtEntry(28, top + 2, "", 20, &n.ns[1], NEWT_ENTRY_SCROLL);
  839.     n.nsEntrys[2] = newtEntry(28, top + 3, "", 20, &n.ns[2], NEWT_ENTRY_SCROLL);
  840.  
  841.     if (!strlen(netc->hostname) && !strlen(netc->domainname) && intf->isUp && 
  842.     netc->nameserver[0]) {
  843.     guessHostname(intf, netc);
  844.     } 
  845.  
  846.     if (netc->hostname)
  847.     newtEntrySet(n.hnEntry, netc->hostname, 0);
  848.  
  849.     if (netc->domainname)
  850.     newtEntrySet(n.dnEntry, netc->domainname, 0);
  851.  
  852.     if (netc->nameserver[1])
  853.     newtEntrySet(n.nsEntrys[1], netc->nameserver[1], 0);
  854.     if (netc->nameserver[2])
  855.     newtEntrySet(n.nsEntrys[2], netc->nameserver[2], 0);
  856.  
  857.     newtComponentAddCallback(n.dnEntry, hnCallback, &n);
  858.  
  859.     f = newtForm(NULL, NULL, 0);
  860.     newtFormAddComponents(f, n.dnLabel, n.hnLabel, n.nsLabels[1], 
  861.               n.nsLabels[2], NULL);
  862.     newtFormAddComponents(f, n.dnEntry, n.hnEntry, n.nsEntrys[1], 
  863.               n.nsEntrys[2], NULL);
  864.  
  865.     okay = newtButton(11, 11, "Ok");
  866.     cancel = newtButton(30, 11, "Cancel");
  867.  
  868.     newtFormAddComponents(f, okay, cancel, NULL);
  869.  
  870.     answer = newtRunForm(f);
  871.  
  872.     strcpy(netc->hostname, n.hn);
  873.     strcpy(netc->domainname, n.dn);
  874.  
  875.     for (i = 1; i < 3; i++) {
  876.     if (netc->nameserver[i]) 
  877.         free(netc->nameserver[i]);
  878.     netc->nameserver[i] = *n.ns[i] ? strdup(n.ns[i]) : NULL;
  879.     }
  880.  
  881.     newtFormDestroy(f);
  882.     newtPopWindow();
  883.  
  884.     if (answer == cancel) return INST_CANCEL;
  885.  
  886.     netc->isConfigured = 1;
  887.  
  888.     return 0;
  889. }
  890.  
  891. int readNetConfig(char * prefix, struct netConfig * netc) {
  892.     FILE * f;
  893.     char * start, * end;
  894.     char buf[250];
  895.     int line = 0;
  896.  
  897.     if (testing) {
  898.     return 0;
  899.     }
  900.  
  901.     sprintf(buf, "%s/network", prefix);
  902.  
  903.     f = fopen(buf, "r");
  904.     if (!f) {
  905.     if (errno != ENOENT) {
  906.         errorWindow("cannot open file: %s");
  907.         return INST_ERROR;
  908.     } else {
  909.         netc->hostname[0] = '\0';
  910.         return 0;
  911.     }
  912.     }
  913.  
  914.     memset(netc, 0, sizeof(*netc));
  915.  
  916.     while (fgets(buf, sizeof(buf) - 1, f)) {
  917.     line++;
  918.  
  919.     start = buf;
  920.  
  921.     /* skipping leading spaces */
  922.     while (*start && isspace(*start)) start++;
  923.     if (!*start) continue;
  924.  
  925.     /* skip comments */
  926.     if (*start == '#') continue;
  927.  
  928.     /* cut off trailing spaces and \n */
  929.     end = start + strlen(start) - 2;
  930.     while (isspace(*end)) end--;
  931.     end++;
  932.     *end = '\0';    
  933.     end--;
  934.     
  935.     if (!strncmp("HOSTNAME=", start, 9)) {
  936.         start += 9;
  937.         strcpy(netc->hostname, start);
  938.     } else if (!strncmp("DOMAINNAME=", start, 11)) {
  939.         start += 11;
  940.         strcpy(netc->domainname, start);
  941.     } else if (!strncmp("GATEWAY=", start, 8)) {
  942.         start += 8;
  943.         strcpy(netc->defaultGateway, start);
  944.     } else if (!strncmp("NS1=", start, 4)) {
  945.         start += 4;
  946.         netc->nameserver[0] = strdup(start);
  947.     } else if (!strncmp("NS2=", start, 4)) {
  948.         start += 4;
  949.         netc->nameserver[1] = strdup(start);
  950.     } else if (!strncmp("NS3=", start, 4)) {
  951.         start += 4;
  952.         netc->nameserver[2] = strdup(start);
  953.     }
  954.     }
  955.  
  956.     fclose(f);
  957.  
  958.     netc->isConfigured = 1;
  959.  
  960.     return 0;
  961. }
  962.  
  963.  
  964. int bringUpNetworking(struct netInterface * intf, struct netConfig * netc,
  965.               struct driversLoaded ** dl) {
  966.     return doBringUpNetworking(intf, netc, dl, 0);
  967. }
  968.  
  969. #define BRINGUP_NET     1
  970. #define BRINGUP_CONF    2
  971. #define BRINGUP_ROUTE    3
  972. #define BRINGUP_DONE    4
  973.  
  974. static int doBringUpNetworking(struct netInterface * intf, 
  975.                    struct netConfig * netc,
  976.                    struct driversLoaded ** dl, int justConfig) {
  977.     int where = BRINGUP_NET;
  978.     int rc;
  979.  
  980.     while (where != BRINGUP_DONE) {
  981.     switch (where) {
  982.       case BRINGUP_NET:
  983.         rc = setupNetworkInterface(intf, netc, dl, justConfig);
  984.         if (rc) return rc;
  985.         where = BRINGUP_CONF;
  986.         break;
  987.  
  988.       case BRINGUP_CONF:
  989.         rc = configureNetwork(netc, intf);
  990.         if (rc == INST_CANCEL)
  991.         where = BRINGUP_NET;
  992.         else if (rc)
  993.         return INST_ERROR;
  994.         else
  995.         where = BRINGUP_ROUTE;
  996.         break;
  997.  
  998.       case BRINGUP_ROUTE:
  999.         if (justConfig)
  1000.         rc = 0;
  1001.         else
  1002.         rc = addDefaultRoute(*netc);
  1003.  
  1004.         if (rc) return rc;
  1005.         where = BRINGUP_DONE;
  1006.         break;
  1007.     }
  1008.     }
  1009.  
  1010.     /* write out the /etc/resolv.conf, as we'll need that to use name services
  1011.        properly */
  1012.     writeResolvConf("/etc", netc);
  1013.  
  1014.     return 0;
  1015. }
  1016.  
  1017. #define CHECKNET_CONFIG        1
  1018. #define CHECKNET_KEEP        2
  1019. #define CHECKNET_NONE        3
  1020. #define CHECKNET_NOBOOTP    4
  1021.  
  1022. static int checkNetConfigPanel(int isConfigured, int useBootp, int * choice) {
  1023.     newtComponent text, okay, cancel;
  1024.     newtComponent f, answer, yes, no, listbox;
  1025.     int which;
  1026.  
  1027.     if (isConfigured) {
  1028.     newtOpenWindow(18, 5, 42, 13, "Network Configuration");
  1029.     text = newtTextbox(1, 1, 40, 2, NEWT_TEXTBOX_WRAP);
  1030.     newtTextboxSetText(text,
  1031.         "LAN networking has already been configured. Do you "
  1032.         "want to:");
  1033.  
  1034.     listbox = newtListbox(8, 4, 0, NEWT_LISTBOX_RETURNEXIT);
  1035.  
  1036.     if (useBootp) {
  1037.         newtListboxAddEntry(listbox, "Use bootp at startup", (void *) 1);
  1038.         newtListboxAddEntry(listbox, "Use the current IP information", 
  1039.                       (void *) 4);
  1040.         newtListboxAddEntry(listbox, "Reconfigure network now",
  1041.                       (void *) 2);
  1042.         newtListboxAddEntry(listbox, "Don't setup networking", (void *) 3);
  1043.     } else {
  1044.         newtListboxAddEntry(listbox, "Keep this setup", (void *) 1);
  1045.         newtListboxAddEntry(listbox, "Reconfigure network now",
  1046.                       (void *) 2);
  1047.         newtListboxAddEntry(listbox, "Don't setup networking", (void *) 3);
  1048.     }
  1049.  
  1050.     okay = newtButton(6, 9, "Ok");
  1051.     cancel = newtButton(23, 9, "Cancel");
  1052.  
  1053.     f = newtForm(NULL, NULL, 0);
  1054.  
  1055.     newtFormAddComponents(f, text, listbox, okay, cancel, NULL);
  1056.  
  1057.     answer = newtRunForm(f);
  1058.     if (answer == cancel) {
  1059.         newtPopWindow();
  1060.         newtFormDestroy(f);
  1061.  
  1062.         return INST_CANCEL;
  1063.     }
  1064.  
  1065.     which = (int) newtListboxGetCurrent(listbox);
  1066.  
  1067.     newtPopWindow();
  1068.     newtFormDestroy(f);
  1069.  
  1070.     if (which == 1)
  1071.         *choice = CHECKNET_KEEP;
  1072.     else if (which == 3)
  1073.         *choice = CHECKNET_NONE;
  1074.     else if (which == 4)
  1075.         *choice = CHECKNET_NOBOOTP;
  1076.     else
  1077.         *choice = CHECKNET_CONFIG;
  1078.     } else {
  1079.     newtOpenWindow(18, 6, 42, 10, "Network Configuration");
  1080.  
  1081.     text = newtTextbox(1, 1, 40, 3, NEWT_TEXTBOX_WRAP);
  1082.     newtTextboxSetText(text,
  1083.         "Do you want to configure LAN (not dialup) networking "
  1084.         "for your installed system?");
  1085.  
  1086.     yes = newtButton(3, 6, " Yes ");
  1087.     no = newtButton(16, 6, "  No  ");
  1088.     cancel = newtButton(29, 6, "Cancel");
  1089.  
  1090.     f = newtForm(NULL, NULL, 0);
  1091.     newtFormAddComponents(f, text, yes, no, cancel, NULL);
  1092.  
  1093.     answer = newtRunForm(f);
  1094.     if (answer == f) 
  1095.         answer = newtFormGetCurrent(f);
  1096.  
  1097.     newtPopWindow();
  1098.     newtFormDestroy(f);
  1099.  
  1100.     if (answer == yes) {
  1101.         *choice = CHECKNET_CONFIG;
  1102.     } else if (answer == cancel) {
  1103.         return INST_CANCEL;
  1104.     } else {
  1105.         *choice = CHECKNET_NONE;
  1106.     }
  1107.     }
  1108.  
  1109.     return 0;
  1110. }
  1111.  
  1112. int checkNetConfig(struct netInterface * intf, struct netConfig * netc,
  1113.            struct driversLoaded ** dl) {
  1114.     int choice, rc;
  1115.  
  1116.     /* this doesn't handle cancel very well as the dl makes it difficult :-( */
  1117.  
  1118.     do {
  1119.     rc = checkNetConfigPanel(netc->isConfigured && intf->isConfigured,
  1120.                  intf->useBootp, &choice);
  1121.     if (rc) return rc;
  1122.  
  1123.     switch (choice) {
  1124.       case CHECKNET_NOBOOTP:
  1125.         intf->useBootp = 0;
  1126.         rc = 0;
  1127.         break;
  1128.  
  1129.       case CHECKNET_CONFIG:
  1130.         rc = doBringUpNetworking(intf, netc, dl, 1);
  1131.         if (rc == INST_ERROR) return rc;
  1132.         break;
  1133.  
  1134.       case CHECKNET_NONE:
  1135.         intf->isConfigured = netc->isConfigured = 0;
  1136.         rc = 0;
  1137.         break;
  1138.     }
  1139.     } while (rc);
  1140.  
  1141.     return 0;
  1142. }
  1143.